#include "asr.h"
#include "stdlib.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>

#include <iostream>
#include <fstream>
#include <map>
#include <algorithm>
#include <utility>
#include <cmath>

#include <sys/time.h>
#include <iomanip>
#include "string.h"
#include<algorithm>
#include "stdlib.h"
#include "string.h"

#include <iostream>
#include <fstream>
#include <map>
#include <algorithm>
#include <utility>
#include <cmath>

#include "scorer.h"
#include <sys/time.h>
#include <iomanip>


const float NUM_FLT_INF = std::numeric_limits<float>::max();
const float NUM_FLT_MIN = std::numeric_limits<float>::min();




void convertAudioToWavBuf(
    char * toBuf,
    char * fromBuf,
    int totalAudioLen)
{
    char * header = toBuf;
    int byteRate = 16 * 16000 * 1 / 8;
    int totalDataLen = totalAudioLen + 36;
    int channels = 1;
    int  longSampleRate = 16000;

    header[0] = 'R'; // RIFF/WAVE header
    header[1] = 'I';
    header[2] = 'F';
    header[3] = 'F';
    header[4] = (char) (totalDataLen & 0xff);
    header[5] = (char) ((totalDataLen >> 8) & 0xff);
    header[6] = (char) ((totalDataLen >> 16) & 0xff);
    header[7] = (char) ((totalDataLen >> 24) & 0xff);
    header[8] = 'W';
    header[9] = 'A';
    header[10] = 'V';
    header[11] = 'E';
    header[12] = 'f'; // 'fmt ' chunk
    header[13] = 'm';
    header[14] = 't';
    header[16] = 16; // 4 bytes: size of 'fmt ' chunk
    header[17] = 0;
    header[18] = 0;
    header[19] = 0;
    header[20] = 1; // format = 1
    header[21] = 0;
    header[22] = (char) channels;
    header[23] = 0;
    header[24] = (char) (longSampleRate & 0xff);
    header[25] = (char) ((longSampleRate >> 8) & 0xff);
    header[26] = (char) ((longSampleRate >> 16) & 0xff);
    header[27] = (char) ((longSampleRate >> 24) & 0xff);
    header[28] = (char) (byteRate & 0xff);
    header[29] = (char) ((byteRate >> 8) & 0xff);
    header[30] = (char) ((byteRate >> 16) & 0xff);
    header[31] = (char) ((byteRate >> 24) & 0xff);
    header[32] = (char) (1 * 16 / 8); // block align
    header[33] = 0;
    header[34] = 16; // bits per sample
    header[35] = 0;
    header[36] = 'd';
    header[37] = 'a';
    header[38] = 't';
    header[39] = 'a';
    header[40] = (char) (totalAudioLen & 0xff);
    header[41] = (char) ((totalAudioLen >> 8) & 0xff);
    header[42] = (char) ((totalAudioLen >> 16) & 0xff);
    header[43] = (char) ((totalAudioLen >> 24) & 0xff);

    memcpy(toBuf+44, fromBuf, totalAudioLen);

}

ASR::ASR():QShape(),
m_xrate(0.1),
  m_yrate(0.01) 
{
    asrInit("../model/am.model",
            "../model/char.txt",
            "../model/lm.model",
            false);
}
ASR::~ASR()
{

}


float ASR::rms_db(float *data, int len)
{
    float powerSum = 0;
    MatrixXf power = Map<MatrixXf>(data,1,len);
    return 10*log10(power.array().square().sum()/(float)len);
}

void ASR::normalize(float *data, int len, float rmsDb, float targetDb)
{
    MatrixXf inMatrix = Map<MatrixXf>(data,1,len);
    float gain = targetDb - rmsDb;

    float adjustVal = pow(10,(gain/(float)20));
    inMatrix = inMatrix * adjustVal;
    memcpy(data,inMatrix.data(),sizeof(float)*len);
}

void  ASR::extract_feat_init(int fs, int strideInMs, int windowInMs)
{ 
    g_f_fs_=0;
    g_f_strideInMs_=0;
    g_f_windowInMs_=0;
    g_f_init_=0;


    g_f_fs_ = fs;
    g_f_strideInMs_ = strideInMs;
    g_f_windowInMs_ = windowInMs;
 

    int strideLen = (int)(0.001 * fs * strideInMs);
    int windowLen = (int)(0.001 * g_f_fs_ * g_f_windowInMs_);

 
    memset(g_f_prevStride_,0,sizeof(float)*strideLen*2);
 
    memset(g_f_tmpBuf_, 0, sizeof(float)*windowLen);
 
    memset(g_f_tmpBuf2_,0,sizeof(float)*(windowLen/2+1));

 
}

void ASR::extract_feat(int len)
{
 

    int strideLen = (int)(0.001 * g_f_fs_ * g_f_strideInMs_);//160
    int windowLen = (int)(0.001 * g_f_fs_ * g_f_windowInMs_);//320
    int truncateLen = (len - windowLen) % strideLen;//0
    int frames = (int)((len - truncateLen)/strideLen);//120

    Eigen::FFT<float> fft;
    MatrixXf hanningData = Map<MatrixXf>(hanning,1,windowLen);//320

    float fsum = hanningData.array().square().sum();
    float scale = fsum*g_f_fs_;
    float scale2 = 2.0/scale;

    float rmsDB = rms_db(m_wavdatabuf,len);
    normalize(m_wavdatabuf,len,rmsDB,-20.0);//filter

  m_debugfeatpoints0.clear();
    for(int i = m_validbegin; i<len-m_validend; i++)
    {
        m_debugfeatpoints0.addapoint(i*m_xrate+rect().x(),rect().y());
        m_debugfeatpoints0.addapoint(i*m_xrate+rect().x(), m_wavdatabuf[i]* m_y1rate+rect().y());
     }



    MatrixXf featMeanMatrix = Map<MatrixXf>(g_mean,1,161);
    MatrixXf featStdMatrix =  Map<MatrixXf>(g_std,1,161);

    int outIdx = 0;
    int retFrames = frames;
    if(g_f_init_ == 0)
    {
        retFrames = retFrames -1 ;
    } 
    if(frames*(windowLen/2+1)>1920000)
        assert(0);
    memset(m_featOut, 0 , sizeof(float)*frames*(windowLen/2+1));

    for(int i = 0; i< frames; i++)
    {
        if(g_f_init_ == 0)
        {
            memcpy(g_f_prevStride_,m_wavdatabuf,2*strideLen*sizeof(float));
            i = i +1;
            g_f_init_ = 1;
        }
        else
        {
            memcpy(g_f_prevStride_+strideLen,m_wavdatabuf+i*strideLen,strideLen*sizeof(float));
        }
        MatrixXf frameData = Map<MatrixXf>(g_f_prevStride_, 1, windowLen);
        MatrixXf frameHanmming = (frameData.array() * hanningData.array()).matrix();

        std::vector<float> vecHanmming;
        vecHanmming.resize(frameHanmming.cols());

        for(int kk = 0; kk<frameHanmming.cols(); kk++)
        {
            vecHanmming[kk] = frameHanmming(0,kk);
        }

        std::vector<std::complex<float> > freqvec;
        fft.fwd(freqvec,vecHanmming);

        memset(g_f_tmpBuf_,0,sizeof(float)*windowLen);

        for(int j = 0; j< windowLen; j++)
        {
            g_f_tmpBuf_[j] = std::abs(freqvec[j]);
        }

        MatrixXf fftMat = Map<MatrixXf>(g_f_tmpBuf_, 1, windowLen);
        fftMat = fftMat.array().square().matrix();

        MatrixXf midFftMat = fftMat.block(0,1,1,windowLen/2-1);

        midFftMat = (midFftMat.array()*scale2+eps).log().matrix();

        memcpy(g_f_tmpBuf2_+1,midFftMat.data(),sizeof(float)*(windowLen/2));
        g_f_tmpBuf2_[0] = log(fftMat.data()[0]/scale+eps);
        g_f_tmpBuf2_[windowLen/2] = log(fftMat.data()[windowLen/2]/scale+eps);

        MatrixXf featTmp = Map<MatrixXf>(g_f_tmpBuf2_,1,161);

        MatrixXf featOutMat = ((featTmp.array() - featMeanMatrix.array())/(featStdMatrix.array()+eps_featnorm)).matrix();
        memcpy(m_featOut+(outIdx++)*(windowLen/2+1),featOutMat.data(),sizeof(float)*(windowLen/2+1));

        memcpy(g_f_prevStride_,g_f_prevStride_+strideLen,strideLen*sizeof(float));
    }
    m_iframesnum = retFrames;

 
}

void ASR::feat_extrace_destroy()
{
} 
void  ASR::am_init()
{

    memset(&g_tmpBuf_,0,sizeof(TMP_BUF_SIZE));
    memset(&g_nn_input_data,0,sizeof(BUF1_SIZE));
    memset(&g_nn_output_data,0,sizeof(BUF2_SIZE));

    float amHeader_[4];
    memcpy(&(amHeader_),g_am_model,sizeof(float)*4);
    QString qstrfile = QString("modelparam.txt");//QString("%1").arg(4)
    savevalue(qstrfile.toStdString().c_str(),amHeader_,4);



    int index = sizeof(AM_HEADER_INFO_t)/sizeof(float);
    for(int i = 0; i< 2; i++)
    {
        memset(&(g_convWt_[i]),0,sizeof(float));
        memset(&(g_bias_[i]),0,sizeof(float));
        memset(&(g_remainData_[i]),0,sizeof(float));
        g_init_[i]=0;
        g_remainLines_[i]=0;
        memset(&(g_weightMatrix_[i]),0,sizeof(MatrixXf));
        memset(&(g_biasMatrix_[i]),0,sizeof(MatrixXf));

        if(i==0)
        {
            g_conv_inX_[0]=161.0;
            g_conv_inY_[0]=372.0;

            g_conv_inCh_[0]=1.0;
            g_conv_outY_[0]=185.0;

            QString qstrfile = QString("nnconv_Info_model_%1.mod").arg(i);//QString("%1").arg(4)
            savevalue(qstrfile.toStdString().c_str(),g_am_model+index,
                      sizeof(NN_CONV_INFO_t)/sizeof(float));


            index = index + sizeof(NN_CONV_INFO_t)/sizeof(float);

            g_convWt_[i] = g_am_model+index;

            g_weightMatrix_[i] = Map<MatrixXf>(g_convWt_[i],9,32);

            QString qstrfile0 = QString("nnconv_weightMatrix_model_%1.mod").arg(i);//QString("%1").arg(4)
            savevalue(qstrfile0.toStdString().c_str(),g_am_model+index,288);//3 3


            index = index + 288 ;

            g_bias_[i] = g_am_model+index;
            g_biasMatrix_[i] = Map<MatrixXf>(g_bias_[i],1,32);//32 32


            QString qstrfile1 = QString("nnconv_biasMatrix_model_%1.mod").arg(i);//QString("%1").arg(4)
            savevalue(qstrfile1.toStdString().c_str(),g_am_model+index,32);

            index = index + 32;

            g_remainData_[i] = new float[483];
            memset(g_remainData_[i], 0 ,sizeof(float) *483);


        }
        else if(i==1)
        {
            g_conv_inX_[1]=80.0;
            g_conv_inY_[1]=185.0;

            g_conv_inCh_[1]=32.0;
            g_conv_outY_[1]=92.0;


            QString qstrfile = QString("nnconv_Info_model_%1.mod").arg(i);//QString("%1").arg(4)
            savevalue(qstrfile.toStdString().c_str(),g_am_model+index,
                      sizeof(NN_CONV_INFO_t)/sizeof(float));


            index = index + sizeof(NN_CONV_INFO_t)/sizeof(float);

            g_convWt_[i] = g_am_model+index;

            g_weightMatrix_[i] = Map<MatrixXf>(g_convWt_[i],288,32);

            QString qstrfile0 = QString("nnconv_weightMatrix_model_%1.mod").arg(i);//QString("%1").arg(4)
            savevalue(qstrfile0.toStdString().c_str(),g_am_model+index,
                      (32*32*3*3));


            index = index + (32*32*3*3) ;

            g_bias_[i] = g_am_model+index;
            g_biasMatrix_[i] = Map<MatrixXf>(g_bias_[i],1,32);


            QString qstrfile1 = QString("nnconv_biasMatrix_model_%1.mod").arg(i);//QString("%1").arg(4)
            savevalue(qstrfile1.toStdString().c_str(),g_am_model+index,32);

            index = index + 32;

            g_remainData_[i] = new float[3*32*80];

            memset(g_remainData_[i], 0 ,sizeof(float) *3*32*80);



        }


    }

    for(int i = 0; i< 5; i++)
    {
        memset(&(g_weightIh_[i]),0,sizeof(float));
        memset(&(g_weightHh_[i]),0,sizeof(float));
        memset(&(g_biasIh_[i]),0,sizeof(float));
        memset(&(g_biasHh_[i]),0,sizeof(float));
        memset(&(g_normWeight_[i]),0,sizeof(float));
        memset(&(g_normBias_[i]),0,sizeof(float));
        memset(&(g_prevHiddenStates_[i]),0,sizeof(float));
        memset(&(g_x2hWeightMatrix_[i]),0,sizeof(MatrixXf));
        memset(&(g_h2hWeightMatrix_[i]),0,sizeof(MatrixXf));
        memset(&(g_x2hBias_[i]),0,sizeof(MatrixXf));
        memset(&(g_h2hBias_[i]),0,sizeof(MatrixXf));
        memset(&(g_normWMat_[i]),0,sizeof(MatrixXf));
        memset(&(g_normBiasMat_[i]),0,sizeof(MatrixXf));

        g_rnn_hiddenSize_[0]=1024.0;
        g_rnn_inputSize_[0]=1248.0;

        g_rnn_hiddenSize_[1]=1024.0;
        g_rnn_inputSize_[1]=1024.0;

        g_rnn_hiddenSize_[2]=1024.0;
        g_rnn_inputSize_[2]=1024.0;

        g_rnn_hiddenSize_[3]=1024.0;
        g_rnn_inputSize_[3]=1024.0;

        g_rnn_hiddenSize_[4]=1024.0;
        g_rnn_inputSize_[4]=1024.0;


        QString qstrfile = QString("rnn_Info_model_%1.mod").arg(i);//QString("%1").arg(4)
        savevalue(qstrfile.toStdString().c_str(),g_am_model+index,
                  sizeof(NN_RNN_INFO_t)/sizeof(float));

        index = index + sizeof(NN_RNN_INFO_t)/sizeof(float);

        g_weightIh_[i] = g_am_model+index;

        g_x2hWeightMatrix_[i] = Map<MatrixXf>(g_weightIh_[i],
                        (int)(g_rnn_hiddenSize_[i]*3),//3072
                       (int)(g_rnn_inputSize_[i]));//1248

        QString qstrfile0 = QString("rnn_x2hWeightMatrix_model_%1.mod").arg(i);//QString("%1").arg(4)
        savevalue(qstrfile0.toStdString().c_str(),g_am_model+index,
                  (int)(g_rnn_inputSize_[i]*3*
                        g_rnn_hiddenSize_[i]));

        index = index + (int)(g_rnn_inputSize_[i]*3*
                             g_rnn_hiddenSize_[i]);

        g_weightHh_[i] = g_am_model+index;

        g_h2hWeightMatrix_[i] = Map<MatrixXf>(g_weightHh_[i],
                                          (int)(g_rnn_hiddenSize_[i]*3),//3072
                                          (int)(g_rnn_hiddenSize_[i]));//1024

        QString qstrfile1 = QString("rnn_h2hWeightMatrix_model_%1.mod").arg(i);//QString("%1").arg(4)
        savevalue(qstrfile1.toStdString().c_str(),g_am_model+index,
                  (int)(g_rnn_hiddenSize_[i]*3*g_rnn_hiddenSize_[i]));

        index = index +(int)(g_rnn_hiddenSize_[i]*3*g_rnn_hiddenSize_[i]);

        g_biasIh_[i] = g_am_model+index;

        g_x2hBias_[i] = Map<MatrixXf>(g_biasIh_[i],
                                  (int)(g_rnn_hiddenSize_[i]*3), 1);

        QString qstrfile2 = QString("rnn_x2hBias_model_%1.mod").arg(i);//QString("%1").arg(4)
        savevalue(qstrfile2.toStdString().c_str(),g_am_model+index,
                  (int)(g_rnn_hiddenSize_[i]*3));

        index = index + (int)(g_rnn_hiddenSize_[i]*3);

        g_biasHh_[i] = g_am_model+index;

        g_h2hBias_[i] = Map<MatrixXf>(g_biasHh_[i],
                                    (int)(g_rnn_hiddenSize_[i]*3),1);

        QString qstrfile3 = QString("rnn_h2hBias_model_%1.mod").arg(i);//QString("%1").arg(4)
        savevalue(qstrfile3.toStdString().c_str(),g_am_model+index,
                  (int)(g_rnn_hiddenSize_[i]*3));

        index = index + (int)(g_rnn_hiddenSize_[i]*3);

        g_normWeight_[i] = g_am_model+index;

        g_normWMat_[i] = Map<MatrixXf>(g_normWeight_[i],1,
                                     (int)g_rnn_hiddenSize_[i]);

        QString qstrfile4 = QString("rnn_normWMat_model_%1.mod").arg(i);//QString("%1").arg(4)
        savevalue(qstrfile4.toStdString().c_str(),g_am_model+index,
                  (int)g_rnn_hiddenSize_[i]);

        index = index + (int)g_rnn_hiddenSize_[i];

        g_normBias_[i] = g_am_model+index;
        g_normBiasMat_[i] = Map<MatrixXf>(g_normBias_[i],1,
                            (int)g_rnn_hiddenSize_[i]);

        QString qstrfile5 = QString("rnn_normBiasMat_model_%1.mod").arg(i);//QString("%1").arg(4)
        savevalue(qstrfile5.toStdString().c_str(),g_am_model+index,
                  (int)g_rnn_hiddenSize_[i]);

        index = index +(int)g_rnn_hiddenSize_[i];

        g_prevHiddenStates_[i] = new float[(int)g_rnn_hiddenSize_[i]];
        memset(g_prevHiddenStates_[i],0,(int)g_rnn_hiddenSize_[i]*sizeof(float));
    }

    for(int i = 0; i< 1; i++)
    {
        memset(&g_fc_nnInfo_[i],0,sizeof(NN_FC_INFO_t));
        memset(&(g_fc_weight_[i]),0,sizeof(float));
        memset(&(g_fc_bias_[i]),0,sizeof(float));
        memset(&(g_fc_weightMat_[i]),0,sizeof(MatrixXf));
        memset(&(g_fc_biasMat_[i]),0,sizeof(MatrixXf));


        memcpy(&(g_fc_nnInfo_[i]),g_am_model+index,sizeof(NN_FC_INFO_t));

        QString qstrfile = QString("fc_param_model_%1.mod").arg(i);//QString("%1").arg(4)
        savevalue(qstrfile.toStdString().c_str(),g_am_model+index,sizeof(NN_FC_INFO_t)/sizeof(float));



        index  = index + sizeof(NN_FC_INFO_t)/sizeof(float);

        g_fc_weight_[i] = g_am_model + index;
        g_fc_weightMat_[i] = Map<MatrixXf>(g_fc_weight_[i],
                             (int)g_fc_nnInfo_[i].inDim_,
                             (int)g_fc_nnInfo_[i].outDim_);

        QString qstrfile0 = QString("fc_weightMat_model_%1.mod").arg(i);//QString("%1").arg(4)
        savevalue(qstrfile0.toStdString().c_str(),g_am_model+index,
                  (int)(g_fc_nnInfo_[i].inDim_ *
                        g_fc_nnInfo_[i].outDim_));


        index = index + (int)(g_fc_nnInfo_[i].inDim_ *
                              g_fc_nnInfo_[i].outDim_);

        g_fc_bias_[i] = g_am_model + index;
        g_fc_biasMat_[i] = Map<MatrixXf>(g_fc_bias_[i],1,(int)g_fc_nnInfo_[i].outDim_);

        QString qstrfile1 = QString("fc_biasMat__model_%1.mod").arg(i);//QString("%1").arg(4)
        savevalue(qstrfile1.toStdString().c_str(),g_am_model+index,
                  (int)(g_fc_nnInfo_[i].outDim_));

        index = index + (int)(g_fc_nnInfo_[i].outDim_);

    }

}
float * ASR::am_run(int & amFrames)
{

    float * inputBuf = (float *)g_nn_input_data;

    int inputpos0 =  161*m_iframesnum;

    memcpy(inputBuf,m_featOut,inputpos0*sizeof(float));

    m_nn_input_data =  g_nn_input_data;//1024*1024*20
    m_nn_output_data = g_nn_output_data;//1024*1024*20

    int nextLayerOffset = 0;

    int iframesnum = m_iframesnum;

    for(int inum = 0; inum<2;inum++)
    {
        int firstConv = g_init_[inum];

        if(g_init_[inum] == 0)
        {
            g_init_[inum] = 1;
        }

        if(inum < 1)
        {
            nextLayerOffset = g_remainLines_[1]*2560;
        }
        else
        {
            nextLayerOffset = 0;
        }
       if(NN_OP_STATUS_SKIP == nn_op_conv2d(inum,
          iframesnum,
          nextLayerOffset))
        {
            g_init_[inum] = firstConv;
            amFrames =-1;
            return NULL;
        }

        if(g_conv_outY_[inum] < 1)
        {
            amFrames =-1;
            return NULL;
        }

        iframesnum = (int)g_conv_outY_[inum];

        if(inum < 1)
        {
            memcpy(m_nn_output_data,
                   g_remainData_[1],
                   g_remainLines_[1]*
                   2560*sizeof(float));
        }
switchbuf();
       }

    for(int i = 0; i<(int)g_conv_outY_[1]; i++)
    {
        for(int j = 0; j< 32; j++)
        {
            for(int k = 0; k<39; k++)
            {
                m_nn_output_data[i*1248 + j*39 + k]
                        = m_nn_input_data[i*1248 + k*32 + j];
            }
        }
    }
switchbuf();

    for(int inum = 0; inum< 5; inum++)
    {
        nn_op_gru(inum);
switchbuf();
        nn_op_norm(inum);
switchbuf();
   }

 


        int inRow = (int)g_conv_outY_[1];
        int inCol = (int)g_rnn_hiddenSize_[4];

        MatrixXf inMat = MatrixXf(inRow,inCol);

        for(int i = 0; i<inRow; i++)
        {
            MatrixXf row = Map<MatrixXf>(m_nn_input_data + i*inCol, 1, inCol);
            inMat.block(i,0,1,inCol) = row.block(0,0,1,inCol);
        }

        MatrixXf outMat = inMat*(g_fc_weightMat_[0]);

        for(int i = 0; i< inRow; i++)
        {
           outMat.row(i) = outMat.row(i) + g_fc_biasMat_[0];
        }

        MatrixXf outMatT = outMat.transpose();

        memcpy(m_nn_output_data,
               outMatT.data(),
               outMatT.rows()*outMatT.cols()*sizeof(float));




switchbuf();


    float * out = new float[(int)g_conv_outY_[1]*6436];
    memset(out,0,sizeof(float)*(int)g_conv_outY_[1]*6436);

    nn_op_softmax(out);

    amFrames = (int)g_conv_outY_[1];

    return out;
}


NN_OP_STATUS_t ASR::nn_op_conv2d(int inum,
                            int iframesnum,
                            int nextLayerOffset)
{
    int Ny = 0;
    int remainOffset = 0;

    if((int)(iframesnum + g_remainLines_[inum]) >= 3)
    {
        Ny = ((int)(iframesnum + g_remainLines_[inum])-3)/2+1;

        g_remainLines_[inum] = (int)(iframesnum + g_remainLines_[inum]) -
                Ny*2;


        remainOffset = ((int)(iframesnum + g_remainLines_[inum]) -
                     g_remainLines_[inum])*
                (int)g_conv_inX_[inum]*
                (int)g_conv_inCh_[inum];
        g_conv_outY_[inum] = (float)Ny;
        memcpy((void *)g_remainData_[inum],
               (void *)(m_nn_input_data+remainOffset),
               g_remainLines_[inum]*(int)g_conv_inX_[inum]*
               (int)g_conv_inCh_[inum]*sizeof(float));
    }
    else
    {
        g_remainLines_[inum] = (int)(iframesnum + g_remainLines_[inum]);
        g_conv_outY_[inum] = 0;
        memcpy((void *)g_remainData_[inum],
               (void *)(m_nn_input_data+remainOffset),
               g_remainLines_[inum]*(int)g_conv_inX_[inum]*
               (int)g_conv_inCh_[inum]*sizeof(float));
        return NN_OP_STATUS_SKIP;
    }

    for (int j = 0; j < (int)(g_conv_outY_[inum]); j++)
    {
        if(0==inum)
        {
            for (int k = 0; k < 80; k++)
            {
                int in_row = 2 * j  ;
                int in_col = 2 * k  ;

               const float * pStart = m_nn_input_data +
                         ((int)161*in_row+in_col);

                int outIdx = 0;
                for(int iy = 0; iy<3; iy++)
                {
                        memcpy((void *)(g_tmpBuf_ + outIdx),
                                       (void *)(pStart+iy*161),
                                       3*sizeof(float));

                        outIdx = outIdx + 3;
                 }

                MatrixXf imInMat =  Map<MatrixXf>(g_tmpBuf_,1,9);
                MatrixXf chOutMat = imInMat *
                        g_weightMatrix_[0] +
                        g_biasMatrix_[0];
                chOutMat = ((((chOutMat.array().pow(3)*
                               0.044715+
                               chOutMat.array())*
                              0.7978845608028654).tanh()+1)*
                            chOutMat.array()*0.5).matrix();

                memcpy(m_nn_output_data+
                       nextLayerOffset+
                       (j*80+k)*
                       32,
                       chOutMat.data(),
                       32*sizeof(float));
            }

        }
        else if(1==inum)
        {
            for (int k = 0; k < 39; k++)
            {
                int in_row = 2 * j  ;
                int in_col = 2 * k  ;

                const float * pStart = m_nn_input_data +
                        (80*in_row+in_col)*32;
                int outIdx = 0;
                for(int iy = 0; iy<3; iy++)
                {
                    memcpy((void *)(g_tmpBuf_ + outIdx),
                                   (void *)(pStart+iy*2560),
                                   96*sizeof(float));

                    outIdx = outIdx + 96;
                }

                MatrixXf imInMat =  Map<MatrixXf>(g_tmpBuf_,
                         1,288);
                MatrixXf chOutMat = imInMat *
                        g_weightMatrix_[1] +
                        g_biasMatrix_[1];
                chOutMat = ((((chOutMat.array().pow(3)*
                               0.044715+
                               chOutMat.array())*
                              0.7978845608028654).tanh()+1)*
                            chOutMat.array()*0.5).matrix();

                memcpy(m_nn_output_data+
                       nextLayerOffset+
                       (j*39+k)*32,
                       chOutMat.data(),
                       32*sizeof(float));
            }
        }
    }

    return NN_OP_STATUS_OK;
}


MatrixXf sigmod(MatrixXf val)
{
    MatrixXf oneMat = MatrixXf::Ones(val.rows(),val.cols());
    return (oneMat.array()/((val.array()*(-1.0)).exp()+1.0)).matrix();
}

NN_OP_STATUS_t ASR::nn_op_gru(int inum)
{
    int seq_length=(int)g_conv_outY_[1];


    float * hidden = (float *)malloc(sizeof(float) * (int)g_rnn_hiddenSize_[inum]);
    memcpy(hidden,g_prevHiddenStates_[inum],sizeof(float) * (int)g_rnn_hiddenSize_[inum]);

    for(int seqIdx = 0; seqIdx < seq_length; seqIdx++)
    {
        MatrixXf inputXMatrix = Map<MatrixXf>(m_nn_input_data +
                                              seqIdx*(int)g_rnn_inputSize_[inum],
                                              (int)g_rnn_inputSize_[inum],1);
        MatrixXf gate_x = g_x2hWeightMatrix_[inum] *
                inputXMatrix + g_x2hBias_[inum];

        MatrixXf hiddenMatrix = Map<MatrixXf>(hidden,(int)g_rnn_hiddenSize_[inum],1);
        MatrixXf gate_h = g_h2hWeightMatrix_[inum] *
                hiddenMatrix + g_h2hBias_[inum];

        MatrixXf i_r = gate_x.block(0,0,(int)g_rnn_hiddenSize_[inum],1);
        MatrixXf i_i = gate_x.block((int)g_rnn_hiddenSize_[inum],0,
                                    (int)g_rnn_hiddenSize_[inum],1);
        MatrixXf i_n = gate_x.block((int)g_rnn_hiddenSize_[inum]*2,0,
                                    (int)g_rnn_hiddenSize_[inum],1);
        MatrixXf h_r = gate_h.block(0,0,(int)g_rnn_hiddenSize_[inum],1);
        MatrixXf h_i = gate_h.block((int)g_rnn_hiddenSize_[inum],0,
                                    (int)g_rnn_hiddenSize_[inum],1);
        MatrixXf h_n = gate_h.block((int)g_rnn_hiddenSize_[inum]*2,0,
                                    (int)g_rnn_hiddenSize_[inum],1);

        MatrixXf resetgate = sigmod(i_r + h_r);
        MatrixXf inputgate = sigmod(i_i + h_i);

        MatrixXf newgate = ((resetgate.array()*h_n.array() +
                             i_n.array()).tanh()).matrix();

        MatrixXf hy = (newgate.array() + inputgate.array() *
                       (hiddenMatrix.array() - newgate.array())).matrix();

        memcpy(m_nn_output_data + seqIdx*(int)g_rnn_hiddenSize_[inum],hy.data(),
               sizeof(float)*(int)g_rnn_hiddenSize_[inum]);
        memcpy(hidden,hy.data(),sizeof(float)*(int)g_rnn_hiddenSize_[inum]);
    }

    memcpy(g_prevHiddenStates_[inum], hidden, sizeof(float)*(int)g_rnn_hiddenSize_[inum]);
    free(hidden);

    return NN_OP_STATUS_OK;
}

NN_OP_STATUS_t ASR::nn_op_norm(int inum)
{
   int len=  g_rnn_hiddenSize_[inum];

    for(int i  = 0; i < (int)g_conv_outY_[1]; i++)
    {
        MatrixXf m = Map<MatrixXf>(m_nn_input_data + i*len, 1, len);
        Eigen::MatrixXf mean = m.rowwise().mean();
        float mean_ = mean(0, 0);
        Eigen::MatrixXf sqsum = (m * m.transpose()).rowwise().sum();
        float sqsum_ = sqsum(0, 0);
        float scale = 1. /(float)len;
        float variance_ = sqsum_ * scale - mean_ * mean_;

        MatrixXf lineNormed =  (((m.array() - mean_)/
                                 sqrt(variance_ + eps_norm))*
                                g_normWMat_[inum].array()+
                                g_normBiasMat_[inum].array()).matrix();

        memcpy(m_nn_output_data+i*len,lineNormed.data(),sizeof(float)*len);
    }
    return NN_OP_STATUS_OK;
}

NN_OP_STATUS_t ASR::nn_op_fc(int inum)
{

    int inRow = (int)g_conv_outY_[1];
    int inCol = (int)g_rnn_hiddenSize_[4];

    MatrixXf inMat = MatrixXf(inRow,inCol);

    for(int i = 0; i<inRow; i++)
    {
        MatrixXf row = Map<MatrixXf>(m_nn_input_data + i*inCol, 1, inCol);
        inMat.block(i,0,1,inCol) = row.block(0,0,1,inCol);
    }

    MatrixXf outMat = inMat*(g_fc_weightMat_[inum]);

    for(int i = 0; i< inRow; i++)
    {
       outMat.row(i) = outMat.row(i) + g_fc_biasMat_[inum];
    }

    MatrixXf outMatT = outMat.transpose();

    memcpy(m_nn_output_data,
           outMatT.data(),
           outMatT.rows()*outMatT.cols()*sizeof(float));
    return NN_OP_STATUS_OK;
}

NN_OP_STATUS_t ASR::nn_op_softmax(float * out)
{

    for(int i = 0; i< (int)g_conv_outY_[1]; i++)
    {
        MatrixXf row = Map<MatrixXf>(m_nn_input_data + i*6436,1,6436);
        MatrixXf m = row.array().exp();
        float sum = m.sum();
        MatrixXf n = m / sum;
        memcpy(out+i*6436,
               n.data(),
               6436*sizeof(float));
    }
    return NN_OP_STATUS_OK;
}


void ASR::savevalue(const char * pchar,float *pvalue,int ilen)
{
   if(ilen<=0)
       return;

  FILE    *rf = fopen(pchar, "w+");

  if ( rf == nullptr)
      return;

  rewind(rf);

  fprintf(rf,"%f",pvalue[0]);

  for(int i=1;i<ilen;i++)
  {

      fprintf(rf,",");

      fprintf(rf,"%f",pvalue[i]);
  }

  fclose(rf);
}




void ASR::switchbuf()
{
    switchBuf(&m_nn_input_data, &m_nn_output_data,g_nn_input_data,g_nn_output_data);

}
void ASR::switchBuf(float ** nn_input_data,
                    float ** nn_output_data,
                    float * buffer1,
                    float * buffer2)
{

    *nn_input_data = *nn_output_data;
    if(*nn_input_data == buffer1)
    {
        *nn_output_data = buffer2;
    }
    else
    {
        *nn_output_data = buffer1;
    }


}


void ASR::am_destroy()
{
 

    for(int i = 0; i< 5; i++)
    {
        delete []g_prevHiddenStates_[i];
    }


}


SEGMENTS_INFO_t * ASR::splitAudio(  int16_t * wavData, int len )
{
    SEGMENTS_INFO_t * retSegs = new SEGMENTS_INFO_t();
    memset(retSegs, 0, sizeof(SEGMENTS_INFO_t));
    
    for(int i = 0; i<VAD_SEGMENT_MAX; i++)
    {
        retSegs->segArray[i].posStart_ = 0;
        retSegs->segArray[i].posEnd_ = 0;
        retSegs->segArray[i].len_ = 0;
        retSegs->segArray[i].eos_ = 0;
        retSegs->segArray[i].segData_ = NULL;
    }

    retSegs->segArray[0].segData_ = wavData;
    retSegs->segNum_ = 0;

    int curSegIdx = 0;
    bool vadActivate = false;
    int vadBlockNum = len/(VAD_BLOCK_SIZE);
    
    for(int i = 0; i<vadBlockNum; i++)
    {
        int pos = 0;
        VAD_RESULT_t vadResult = vad_sdk_run(g_vadData_, (char *)(wavData+i*VAD_BLOCK_SIZE), VAD_BLOCK_SIZE*2, &pos);
                
        if(vadResult != g_prevVadResult_)
        {
            if(g_prevVadResult_ == VAD_OFF)
            {
                int startIdx = i;
                if(startIdx > 40)
                {
                    startIdx = startIdx - 40; 
                }
                else
                {
                    startIdx = 0;
                }

                retSegs->segArray[curSegIdx].posStart_ = (startIdx)*VAD_BLOCK_SIZE;
                retSegs->segArray[curSegIdx].segData_ = wavData+(startIdx)*VAD_BLOCK_SIZE; 
            }
            else 
            {
                retSegs->segArray[curSegIdx].posEnd_ = (i+1)*VAD_BLOCK_SIZE;
                retSegs->segArray[curSegIdx].len_ = retSegs->segArray[curSegIdx].posEnd_ - retSegs->segArray[curSegIdx].posStart_;
                retSegs->segArray[curSegIdx].eos_ = 1;
                if(curSegIdx < VAD_SEGMENT_MAX)
                {
                    curSegIdx = curSegIdx+1;
                }
            }
            vadActivate = true;
            g_prevVadResult_ = vadResult;
        }
        else if(g_prevVadResult_ == VAD_ON)
        {
            retSegs->segArray[curSegIdx].posEnd_ = (i+1)*VAD_BLOCK_SIZE;
            vadActivate = true;
        }
    }

    if(vadActivate == true)
    {
        retSegs->segNum_ = curSegIdx+1;

        if(retSegs->segArray[retSegs->segNum_-1].len_ == 0)
        {
            retSegs->segArray[retSegs->segNum_-1].len_ = len - retSegs->segArray[retSegs->segNum_-1].posStart_;
        }
    }
    
    return retSegs;
}

int ASR::asrLoadAMModel(char * amModelName )
{

    struct stat st;
    if(-1 == stat(amModelName, &st))
    {
        return -1 ;
    }

    FILE *fp = fopen(amModelName, "rb");
    if(!fp)
    {
        printf("Fail to open am model file:%s!\n", amModelName);
        return -1;
    }
 

    fread(g_mean,161*sizeof(float),1,fp);
    fread(g_std,161*sizeof(float),1,fp);
    fread(g_am_model,st.st_size-161*2*sizeof(float),1,fp);
    fclose(fp);
 
    return 0;
}
void ASR::asrInit(char * amModelName, char * labelFile, char * lmFile,  bool streamOn)
{ 
    asrLoadAMModel(amModelName);
    am_init(); 
    extract_feat_init(16000,10,20);
    m_vocab.resize(6436); 

	std::ifstream v;
	v.open(labelFile);

    for (int j=0;j<6436;j++)
	{
        v>>m_vocab[j];
	}
    v.close();
 
    memset(g_amOutBuf_,0,sizeof(float)*AM_OUT_BUF_SIZE);

    g_curFramePos_ = 0;
    g_vadOn_ = true;
    g_streamOn_ = streamOn;

    g_prevVadResult_ = VAD_OFF;
    if(g_vadOn_ == true)
    {
        g_vadData_ = vad_sdk_init();
    }
    else
    {
        g_vadData_ = NULL;
    }

	float alpha = 1.5;
    float beta = 1.0;
    m_score.set(alpha,beta,lmFile);
    g_p_score = &m_score; 

}


 
template <typename T>
T log_sum_exp(const T &x, const T &y)
{
    static T num_min = -std::numeric_limits<T>::max();
    if (x <= num_min) return y;
    if (y <= num_min) return x;
    T xmax = std::max(x, y);
    return std::log(std::exp(x - xmax) + std::exp(y - xmax)) + xmax;
}


template <typename T1, typename T2>
bool pair_comp_first_rev(const std::pair<T1, T2> a, const std::pair<T1, T2> b) {
    return a.first > b.first;
}

template <typename T1, typename T2>
bool pair_comp_second_rev(const std::pair<T1, T2> a, const std::pair<T1, T2> b) {
    return a.second > b.second;
}

/* CTC beam search decoder in C++, the interface is consistent with the original
   decoder in Python version.
*/
vectpart_f_str ASR::ctc_beam_search_decoder(std::vector<std::vector<float> > probs_seq,
                                   int beam_size, //
                                   int blank_id,
                                   float cutoff_prob)
{ 
    Scorer *ext_scorer = g_p_score;
    int num_time_steps = probs_seq.size();

 
    std::map<std::string, float> prefix_set_prev, prefix_set_next;
    // probability of prefixes ending with blank and non-blank
    std::map<std::string, float> probs_b_prev, probs_nb_prev;
    std::map<std::string, float> probs_b_cur, probs_nb_cur;
    prefix_set_prev[" "] = 0;
    probs_b_prev[" "] = 0;
    probs_nb_prev[" "] = -NUM_FLT_INF;

    for (int time_step=0; time_step<num_time_steps; time_step++)
    {
    //	std::cout<<"The "<<time_step<<" frame is decoding"<<std::endl;
        prefix_set_next.clear();
        probs_b_cur.clear();
        probs_nb_cur.clear();
        std::vector<float> prob = probs_seq[time_step];

        std::vector<std::pair<int, float> > prob_idx;
                std::vector<std::pair<int, float>> log_prob_idx;
        for (int i = 0; i < prob.size(); i++)
        {
              prob_idx.push_back(std::pair<int,float>(i, prob[i]));
        }
        // pruning of vacobulary
        std::sort(prob_idx.begin(), prob_idx.end(), pair_comp_second_rev<int, float>);
        if (cutoff_prob < 1.0)
        {
           float cum_prob = 0.0;
           int cutoff_len = 0;
           for (int i=0; i < prob_idx.size(); i++)
           {
             //cum_prob += std::exp(prob_idx[i].second);
              cum_prob += prob_idx[i].second;
              cutoff_len += 1;
              if (cum_prob >= cutoff_prob) break;
           }
           prob_idx = std::vector<std::pair<int, float> >(prob_idx.begin(), prob_idx.begin()+cutoff_len);
                     for (int i = 0; i < cutoff_len; ++i)
                         log_prob_idx.push_back(std::pair<int, float>(prob_idx[i].first, std::log(prob_idx[i].second + NUM_FLT_MIN)));
        }
        // extend prefix
        for (std::map<std::string, float>::iterator it = prefix_set_prev.begin();
            it != prefix_set_prev.end(); it++)
         {
            std::string l = it->first;
//						std::cout<<l<<"\n";
            if( prefix_set_next.find(l) == prefix_set_next.end())
                        {
                probs_b_cur[l] = probs_nb_cur[l] = -NUM_FLT_INF;
         }

         for (int index=0; index<log_prob_idx.size(); index++)
         {
                int c = log_prob_idx[index].first;
                float prob_c = log_prob_idx[index].second;
                if (c == blank_id)
                {
                    probs_b_cur[l] = log_sum_exp(probs_b_cur[l],(prob_c+(log_sum_exp(probs_b_prev[l],probs_nb_prev[l]))));
                }
                else
                {
                    std::string last_char = l.substr(l.size()-1, 1);
                    std::string new_char = m_vocab[c];
                    std::string l_plus = l+" "+new_char;

                    if( prefix_set_next.find(l_plus) == prefix_set_next.end())
                    {
                        probs_b_cur[l_plus] = probs_nb_cur[l_plus] = -NUM_FLT_INF;
                    }

                    if (last_char == new_char)
                    {
                        probs_nb_cur[l_plus] =log_sum_exp(probs_nb_cur[l_plus],(prob_c + probs_b_prev[l]));
                        probs_nb_cur[l] =log_sum_exp(probs_nb_cur[l], (prob_c +probs_nb_prev[l]));
                    }
                    else
                    {//Add Language model
                        float score = 0.0;
                        if (ext_scorer != NULL && l.size() > 1)
                        {
                            score = ext_scorer->get_score(l.substr(1));
                        }
                        probs_nb_cur[l_plus] = log_sum_exp(probs_nb_cur[l_plus],(score +prob_c +log_sum_exp (
                            probs_b_prev[l],probs_nb_prev[l])));
                    }
                    prefix_set_next[l_plus] = log_sum_exp(probs_nb_cur[l_plus],probs_b_cur[l_plus]);
                }

         }

         prefix_set_next[l] = log_sum_exp(probs_b_cur[l],probs_nb_cur[l]);
    }

        probs_b_prev = probs_b_cur;
        probs_nb_prev = probs_nb_cur;
        std::vector<std::pair<std::string, float> >
                  prefix_vec_next(prefix_set_next.begin(), prefix_set_next.end());
        std::sort(prefix_vec_next.begin(), prefix_vec_next.end(), pair_comp_second_rev<std::string, float>);
        int k = beam_size<prefix_vec_next.size() ? beam_size : prefix_vec_next.size();
        prefix_set_prev = std::map<std::string, float>
                  (prefix_vec_next.begin(), prefix_vec_next.begin()+k);
    }
    // post processing
    vectpart_f_str beam_result;
    for (std::map<std::string, float>::iterator it = prefix_set_prev.begin();
         it != prefix_set_prev.end(); it++)
     {
        if (it->second > -NUM_FLT_INF && it->first.size() > 1)
         {
            float prob = it->second;
            std::string sentence = it->first.substr(1);
            // scoring the last word
            if (ext_scorer != NULL && sentence[sentence.size()-1] != ' ')
            {
                prob = prob + ext_scorer->get_score(sentence);
            }
            float log_prob = prob;
            beam_result.push_back(std::pair<float, std::string>(log_prob, sentence));
        }
    }
    // sort the result and return
    std::sort(beam_result.begin(), beam_result.end(), pair_comp_first_rev<float, std::string>);
    return beam_result;
}






void ASR::setfilter(int ibegin,int iend)
{
 m_validbegin = ibegin;
 m_validend = iend;

}
std::string  ASR::doDecode()
{
 
   int num_frames = g_curFramePos_;
 
   int num_classes = 6436;
    int beam_size = 100;
	int blank_id = 0;
	float cutoff_prob = 0.95;
	float alpha = 1.5;
	float beta = 1.0;

    std::vector<std::vector<float> > probs_seq(num_frames,
                           std::vector<float>(num_classes));
    vectpart_f_str result;

	int i=0;
	while(i<num_frames)
	{
		for (int j=0;j<num_classes;j++)
		{
            probs_seq[i][j] = g_amOutBuf_[i*num_classes+j];
		}
		i++;
	}
 
    result = ctc_beam_search_decoder(probs_seq,
                                   beam_size,
                                   blank_id,
                                   cutoff_prob);

    std::string asrResult = "";
    if(result.size() >0)
    {
 
        asrResult = result[0].second;
    }
    
    asrResult.erase(remove(asrResult.begin(),asrResult.end(),' '),asrResult.end());
    return asrResult;
}
void ASR::setrate(double dratex,double dratey,double dratey0,double dratey1)
{
    m_xrate = dratex;
    m_yrate = dratey;
    m_y0rate = dratey0;
    m_y1rate = dratey1;
}

void ASR::setdebug(double dfratey0,double dfratey1)
{
    m_yfrate0 = dfratey0;
    m_yfrate1 = dfratey1;
}
std::string  ASR::doAsr(int16_t * wavData, int len, int eos, bool streamOn)
{
 
    if(len>=192000)
        assert(0);
    memset(m_wavdatabuf,0,sizeof(float)*len);
    m_wavpoints.clear();
    m_datapoints.clear();
 
    for(int i = m_validbegin; i<len-m_validend; i++)
    {
        m_wavdatabuf[i] = (float)wavData[i]/32768.0;

        m_datapoints.addapoint(i*m_xrate+rect().x(),rect().y());
        m_datapoints.addapoint(i*m_xrate+rect().x(),m_wavdatabuf[i]*m_y0rate+rect().y());

        m_wavpoints.addapoint(i*m_xrate+rect().x(),rect().y());
        m_wavpoints.addapoint(i*m_xrate+rect().x(),wavData[i]*m_yrate+rect().y());

    }

    m_featresultpoints.clear();
    m_iframesnum = 0;
 
    extract_feat(len);
    int ixfr = 0;
    for(int i = 0; i<m_iframesnum; i++)
    {
        int strideLen = (int)(0.001 * g_f_fs_ * g_f_strideInMs_);//160

        for(int j = 0; j<strideLen; j++)
        {

            m_featresultpoints.addapoint(ixfr*m_xrate+rect().x(),rect().y());
            m_featresultpoints.addapoint(ixfr*m_xrate+rect().x(),m_featOut[i]*m_yfrate0+rect().y());
            ixfr = ixfr + 1;
        }
    }
    std::string asrResult = "";
 
        int amFrames = 0;
        float * probOut  = am_run(amFrames);

        if((amFrames > 0)&&((6436*(g_curFramePos_+amFrames))<AM_OUT_BUF_SIZE))
        {
            memcpy(g_amOutBuf_+6436*(g_curFramePos_),
                   probOut,
                   6436*amFrames*sizeof(float));
            g_curFramePos_ = g_curFramePos_ + amFrames;
        }

        if((amFrames > 0)&&(streamOn == true))
        {
            asrResult = doDecode();
        }

        if(eos == 1)
        {
            asrResult = doDecode();
            g_curFramePos_ = 0;
        }

 
        delete []probOut;
 
    return asrResult;
}

std::string  ASR::asrRun_without_vad( int16_t * wavData, int len)
{
 
    std::string asrResult = "";
    asrResult =  doAsr(  wavData, len, 1,g_streamOn_);
    return asrResult;
}

std::vector<std::string>  ASR::asrRun_with_vad( int16_t * wavData, int len)
{
 
    std::vector<std::string> result;

    SEGMENTS_INFO_t * segInfo = splitAudio( wavData, len);
    
    for(int i = 0; i< segInfo->segNum_; i++)
    {
        if(segInfo->segArray[i].posEnd_ - segInfo->segArray[i].posStart_ > 160)
        {
            std::string oneResult="";
            oneResult = doAsr( segInfo->segArray[i].segData_,
                               segInfo->segArray[i].posEnd_ - segInfo->segArray[i].posStart_,
                               segInfo->segArray[i].eos_,
                               g_streamOn_);
            result.push_back(oneResult);
        }
    }

    delete segInfo;
    return result;
} 

void ASR::asra(const char *wavfile)
{
    struct stat st;

    if(-1 == stat(wavfile, &st))
    {
        return ;
    }
    FILE *fp = fopen(wavfile, "rb");
    if(!fp)
    {
        printf("Fail to open wav file:in.wav!\n");
        return ;
    }

    fseek(fp, 44, SEEK_SET);

    float wavDur = (float)((st.st_size-44)/32000.0);

    int16_t * wavBuf = (int16_t *)malloc(st.st_size-44);
    fread(wavBuf,st.st_size-44, 1, fp);
    fclose(fp);


    std::string asrResult =  asrRun_without_vad(wavBuf, (((st.st_size)-44)/2));

  
    printf("Asr Result: %s\n",asrResult.c_str());

    setresult(asrResult.c_str());
 }
void ASR::setshow(int ishow)
{
    QShape::setshow(ishow);
}

void ASR::setrect(int ix, int iy, int iw, int ih)
{
    QShape::setrect(ix,iy,iw,ih);
}
void ASR::drawshape(QPainter &painter,QPalette &pal)
{

    QShape::drawshape(painter,pal);
}
void ASR::drawshapex(QPainter &painter,QPalette &pal,
                      double dmovx,double dmovy,
                      double dangle,
                      double dzoomx,double dzoomy)
{
    painter.setPen(QColor(0,255,0));
    painter.setBrush(QColor(0,255,0));

    QString strshow = result();

    double dx = rect().x()*dzoomx+dmovx;
    double dy = rect().y()*dzoomy+dmovy;

    painter.drawText(QRect(dx,dy,180,30),Qt::AlignTop & Qt::AlignRight,strshow);
if(2==show())
{

    m_wavpoints.setshow(7);
    m_wavpoints.setPen(0,255,0);
    m_wavpoints.drawshapex(painter,dmovx,dmovy,
                           dangle,dzoomx, dzoomy);

    m_datapoints.setshow(7);
    m_datapoints.setPen(0,0,255);
    m_datapoints.drawshapex(painter,dmovx,dmovy,
                            dangle,dzoomx, dzoomy);


    m_debugfeatpoints0.setshow(7);
    m_debugfeatpoints0.setPen(155,0,0);
    m_debugfeatpoints0.drawshapex(painter,dmovx,dmovy,
                            dangle,dzoomx, dzoomy);

    m_featresultpoints.setshow(7);
    m_featresultpoints.setPen(155,155,0);
    m_featresultpoints.drawshapex(painter,dmovx,dmovy,
                            dangle,dzoomx, dzoomy);



 }

QShape::drawshapex(painter,pal,dmovx,dmovy,
                            dangle,dzoomx, dzoomy);
}

